package com.joysuch.wwyt.attendance.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joysuch.wwyt.attendance.bean.AttendanceGroupShiftBean;
import com.joysuch.wwyt.attendance.bean.AttendanceGroupShiftListBean;
import com.joysuch.wwyt.attendance.bean.AttendanceShiftParam;
import com.joysuch.wwyt.attendance.dto.AttendanceGroupShiftDto;
import com.joysuch.wwyt.attendance.dto.AttendanceShiftDto;
import com.joysuch.wwyt.attendance.entity.AttendanceGroup;
import com.joysuch.wwyt.attendance.entity.AttendanceShift;
import com.joysuch.wwyt.attendance.mapper.AttendanceGroupMapper;
import com.joysuch.wwyt.attendance.mapper.AttendanceShiftMapper;
import com.joysuch.wwyt.attendance.service.AttendanceShiftService;
import com.joysuch.wwyt.attendance.vo.AttendanceShiftVo;
import com.joysuch.wwyt.core.bean.SimpleListBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.enums.DeleteFlag;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.support.Context;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zqw
 * @since 2022-02-28
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AttendanceShiftServiceImpl extends ServiceImpl<AttendanceShiftMapper, AttendanceShift> implements AttendanceShiftService {

    @Autowired
    private AttendanceShiftService shiftService;

    @Autowired
    private AttendanceShiftMapper shiftMapper;

    @Autowired
    private AttendanceGroupMapper groupMapper;

    @Override
    public AttendanceShift saveShift(AttendanceShiftDto dto) throws ApiBusinessException {
        AttendanceShift shift = new AttendanceShift();
        int count = 0;
        if (dto.getId() != null) {
            shift = shiftService.getById(dto.getId());
            count = shiftMapper.findByNameAndIdNotEq(dto.getShiftName(), dto.getId(), Context.getCompanyCode(), Context.getCurrentTenantId());
        } else {
            count = shiftMapper.findByName(dto.getShiftName(), Context.getCompanyCode(), Context.getCurrentTenantId());
        }
        if (count > 0) {
            throw new ApiBusinessException(Status.DUPLICATE_ATTENDANCE_SHIFT_NAME);
        }
        BeanUtils.copyProperties(dto, shift);
        LocalTime startTime = DateTimeUtil.String2LocalTime(dto.getStartTime(), "HH:mm");
        LocalTime endTime = DateTimeUtil.String2LocalTime(dto.getEndTime(), "HH:mm");
        shift.setCrossdayFlag(0);
        shift.setBreakFlag(0);
        if (startTime == null && endTime == null) {
            shift.setBreakFlag(1);
        } else if ((startTime == null && endTime != null) || ((startTime != null && endTime == null))) {
            throw new ApiBusinessException(Status.ATTENDANCE_SHIFT_TIME_ERROR);
        } else {
            if (startTime.isAfter(endTime)) {
                //跨日
                shift.setCrossdayFlag(1);
            }
        }
        shiftService.saveOrUpdate(shift);
        return shift;
    }

    @Override
    public AttendanceShiftDto findById(Long id) {
        AttendanceShift shift = shiftService.getById(id);
        AttendanceShiftDto bean = new AttendanceShiftDto();
        if (shift != null) {
            BeanUtils.copyProperties(shift, bean);
        }
        return bean;
    }

    @Override
    public ResultBean pageShift(AttendanceShiftParam pageParam) {
        Page page = (Page) shiftService.page(new Page<>(pageParam.getPageNumber() + 1, pageParam.getPageSize())
                , new QueryWrapper<AttendanceShift>().lambda()
                        .like(pageParam.getShiftName() != null, AttendanceShift::getShiftName, pageParam.getShiftName())
                        .likeRight(AttendanceShift::getOrgCode, Context.getCompanyCode())
                        .eq(AttendanceShift::getTenentId, Context.getCurrentTenantId())
                        .eq(AttendanceShift::getDeleteFlag, '0')
                        .orderBy(true, false, AttendanceShift::getUpdateTime));
        Object collect = page.getRecords();
        if (!CollectionUtils.isEmpty(page.getRecords())) {
            collect = page.getRecords().stream().map(e -> {
                AttendanceShift shift = (AttendanceShift) e;
                AttendanceShiftVo vo = new AttendanceShiftVo();
                BeanUtils.copyProperties(shift, vo);
                if (shift.getBreakFlag().intValue() == 1) {
                    vo.setShiftAttendanceTime("");
                } else {
                    if (shift.getCrossdayFlag().intValue() == 1) {
                        vo.setShiftAttendanceTime(shift.getStartTime() + "-" + shift.getEndTime() + "(次日)");
                    } else {
                        vo.setShiftAttendanceTime(shift.getStartTime() + "-" + shift.getEndTime());
                    }
                }
                return vo;
            }).collect(Collectors.toList());
        }
        return ResultBean.pageData((List) collect, page.getTotal());
    }

    @Override
    public void deleteById(Long id) throws ApiBusinessException {
        shiftDeleteCheck(id);
        AttendanceShift shift = shiftMapper.selectById(id);
        shift.setDeleteFlag(DeleteFlag.DELETED.getCode());
        shiftMapper.updateById(shift);
    }

    @Override
    public List<AttendanceShift> getByIds(List<Long> shiftIds) {
        return shiftService.lambdaQuery().in(AttendanceShift::getId, shiftIds).list();
    }

    @Override
    public List<AttendanceGroupShiftListBean> getShiftsByGroupId(Long groupId) {
        List<AttendanceGroupShiftListBean> list = new ArrayList<>();
        AttendanceGroup group = groupMapper.selectById(groupId);
        List<AttendanceShift> shiftList = getShiftsByGroup(group);
        if (group != null && !CollectionUtils.isEmpty(shiftList)) {
            Integer attendanceFlag = group.getAttendanceFlag();
            for (AttendanceShift shift : shiftList) {
                AttendanceGroupShiftListBean bean = new AttendanceGroupShiftListBean();
                BeanUtils.copyProperties(shift, bean);
                bean.setShiftId(shift.getId());
                bean.setFlag(0);
                list.add(bean);
            }
            if (attendanceFlag.intValue() == 1) {
                AttendanceGroupShiftListBean bean = new AttendanceGroupShiftListBean();
                bean.setShiftName("按排班周期");
                bean.setFlag(1);
                bean.setBreakFlag(0);
                list.add(bean);
            }
        }
        return list;
    }

    private List<AttendanceShift> getShiftsByGroup(AttendanceGroup group) {
        List<AttendanceShift> shiftList = new ArrayList<>();
        if (group == null) {
            return shiftList;
        }
        String json = group.getAttendanceJson();
        if (StringUtils.isBlank(json)) {
            return shiftList;
        }
        List<Long> shiftIds = new ArrayList<>();
        List<AttendanceGroupShiftDto> shiftDtos = JSONArray.parseArray(json, AttendanceGroupShiftDto.class);
        for (AttendanceGroupShiftDto dto : shiftDtos) {
            if (!CollectionUtils.isEmpty(dto.getShiftList())) {
                dto.getShiftList().forEach(e -> {
                    if (!shiftIds.contains(e)) {
                        shiftIds.add(e);
                    }
                });
            }
        }
        if (!CollectionUtils.isEmpty(shiftIds)) {
            shiftList = shiftMapper.selectBatchIds(shiftIds);
        }
        return shiftList;
    }

    @Override
    public Map<Long, AttendanceGroupShiftBean> getShiftBeanMapFromGroup(AttendanceGroup group) {
        Map<Long, AttendanceGroupShiftBean> map = new HashMap<>();
        List<AttendanceShift> all = new ArrayList<>();
        if (group != null) {
            all = getShiftsByGroup(group);
        } else {
            all = shiftMapper.findAll(Context.getCompanyCode(), Context.getCurrentTenantId());
        }
        if (!CollectionUtils.isEmpty(all)) {
            all.forEach(s -> {
                AttendanceGroupShiftBean shiftBean = new AttendanceGroupShiftBean();
                shiftBean.setShiftId(s.getId());
                shiftBean.setOriginalName(s.getShiftName());
                if (s.getBreakFlag().intValue() == 1) {
                    shiftBean.setShiftName(s.getShiftName());
                } else {
                    if (s.getCrossdayFlag().intValue() == 1) {
                        shiftBean.setShiftName(s.getShiftName() + "(" + s.getStartTime() + "-" + s.getEndTime() + "(次日))");
                    } else {
                        shiftBean.setShiftName(s.getShiftName() + "(" + s.getStartTime() + "-" + s.getEndTime() + ")");
                    }
                }
                map.put(s.getId(), shiftBean);
            });
        }
        return map;
    }

    @Override
    public Map<String, AttendanceShift> getShifNameMap(AttendanceGroup group) {
        Map<String, AttendanceShift> map = new HashMap<>();
        List<AttendanceShift> all = getShiftsByGroup(group);
        if (!CollectionUtils.isEmpty(all)) {
            all.forEach(s -> {
                map.put(s.getShiftName(), s);
            });
        }
        return map;
    }

    @Override
    public List<SimpleListBean> getTitleByGroupId(Long groupId) {
        List<SimpleListBean> list = new ArrayList<>();
        AttendanceGroup group = groupMapper.selectById(groupId);
        if (group == null) {
            return list;
        }
        List<AttendanceShift> shifts = getShiftsByGroup(group);
        if (CollectionUtils.isEmpty(shifts)) {
            return list;
        }
        shifts.forEach(shift -> {
            SimpleListBean bean = new SimpleListBean();
            bean.setId(shift.getId());
            if (shift.getBreakFlag().intValue() == 1) {
                bean.setName(shift.getShiftName());
            } else {
                if (shift.getCrossdayFlag().intValue() == 1) {
                    bean.setName(shift.getShiftName() + "(" + shift.getStartTime() + "-" + shift.getEndTime() + "(次日))");
                } else {
                    bean.setName(shift.getShiftName() + "(" + shift.getStartTime() + "-" + shift.getEndTime() + ")");
                }
            }
            list.add(bean);
        });
        return list;
    }

    private void shiftDeleteCheck(Long shiftId) throws ApiBusinessException {
        List<Long> shiftIds = new ArrayList<>();
        List<AttendanceGroup> groupList = groupMapper.getAllGroups(null, Context.getCompanyCode(), Context.getCurrentTenantId());
        if (!CollectionUtils.isEmpty(groupList)) {
            for (AttendanceGroup group : groupList) {
                String json = group.getAttendanceJson();
                if (StringUtils.isNotBlank(json)) {
                    List<AttendanceGroupShiftDto> shiftDtos = JSON.parseArray(json, AttendanceGroupShiftDto.class);
                    for (AttendanceGroupShiftDto dto : shiftDtos) {
                        shiftIds.addAll(dto.getShiftList());
                    }
                }
            }
        }
        shiftIds = shiftIds.stream().distinct().collect(Collectors.toList());
        if (shiftIds.contains(shiftId)) {
            throw new ApiBusinessException(Status.ATTENDANCE_SHIFTS_HAVE_BEEN_REFERENCED);
        }
    }
}
